package hyl.core.data;

import hyl.core.MyFun;
import hyl.core.fun.MyByte;

/**
 * 过期类型数据 带有时间戳 <br>
 * 
 * 数据库保存 时 value= 时间戳+数据 <br>
 * 
 * 读取到内存 时 value 解析成 时间戳,b数据,t数据 <br>
 * 
 * @author 37798955@qq.com
 *
 * @param <T>
 */
public class ExData<T> {
	T t数据;
	// 值
	byte[] b数据;
	long l时间戳 = 0;
	IParse<byte[], T> _转换器 = null;
	public void set转换器(IParse<byte[], T> 解析器) {
		if (解析器==null) {
			_转换器=new IParse<byte[], T>(){
				@Override
				public T s2t(byte[] 对象) {
					return ExManager.kryo.deserialize(对象);
				}

				@Override
				public byte[] t2s(T 对象) {
					return ExManager.kryo.serialize(对象);
				}				
			};
		}else
			_转换器 = 解析器;
	}
	/**
	 * 初始化一个空的过期值对象
	 * 
	 * @param 转换器
	 */
	public ExData(IParse<byte[], T> 转换器) {
		set转换器( 转换器);
	}

	public ExData() {
		set转换器( null);
	}

	public ExData(byte[] 保存数据) {
		loadBytes(保存数据);
	}
	

	/**
	 * 从数据库读取数据后解析 注意这里是数据保存的数据(带有时间戳,需要分离)
	 * 
	 * @param 转换器
	 * @param 保存数据
	 */
	public ExData(IParse<byte[], T> 转换器, byte[] 保存数据) {
		set转换器( 转换器);
		loadBytes(保存数据);
	}

	@SuppressWarnings("unchecked")
	protected void s2t(byte[] 数据) {
		if (_转换器 == null)
			t数据 = (T) 数据;
		else
			t数据 = _转换器.s2t(数据);
	}

	protected void t2s(T 数据) {
		if (_转换器 == null)
			b数据 = (byte[]) 数据;
		else
			b数据 = _转换器.t2s(数据);
	}

	

	/**
	 * 更新值
	 * 
	 * @param value
	 */
	public ExData<T> setBytes(byte[] value) {
		b数据 = value;
		s2t(value);
		l时间戳 = MyFun.getMs();
		return this;
	}

	/**
	 * 更新值
	 * 
	 * @param value
	 */
	public ExData<T> setValue(T value) {
		t数据 = value;
		t2s(value);
		l时间戳 = MyFun.getMs();
		return this;
				 
	}

	public byte[] getBytes() {
		l时间戳 = MyFun.getMs();
		return b数据;
	}

	public long get时间戳() {
		return l时间戳;
	}

	public T getValue() {
		l时间戳 = MyFun.getMs();
		return t数据;
	}

	public boolean is过期(long 过期毫秒) {
		if (过期毫秒 <= 0)
			return false;
		if ((MyFun.getMs() - l时间戳) > 过期毫秒)
			return true;
		else
			return false;
	}
	/**
	 * 载入数据 注意这里是数据保存的数据(带有时间戳,需要分离)
	 * 
	 * @param value
	 */
	public synchronized ExData<T> loadBytes(byte[] 保存数据) {
		l时间戳 = MyFun.byteArray2Long(MyByte.subBytes(保存数据, 0, 8));
		b数据 = MyByte.subBytes(保存数据, 8);
		s2t(b数据);
		return this;
	}
	public byte[] getSaveBytes() {
		return MyFun.concat(MyFun.long2ByteArray(l时间戳), b数据);
	}
}
